package com.xc.disk.config.aspect;

import com.xc.disk.exception.OperateException;
import com.xc.disk.info.TokenInfo;
import com.xc.disk.service.AuthorizeService;
import com.xc.tool.utils.IpUtils;
import com.xc.tool.utils.JSONUtils;
import com.xc.tool.utils.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Stream;

/**
 * <p>项目名称: Stars</p>
 * <p>描述: 业务日志记录类</p>
 * <P>创建人: 小程</p>
 * <P>创建人邮箱: 779943476@qq.com</p>
 * <p>创建时间: 2019/7/2</p>
 *
 * @version v1.0
 */
@Aspect
@Component
@Slf4j
@Order(4)
public class LogAspect extends AbstractPoint {


    @Autowired
    private AuthorizeService authorizeService;


    /**
     * <p>功能描述: 请求日志记录 </p>
     * <p>更新人: 小程</p>
     * <p>更新描述: 添加方法</p>
     * <p>更新人邮箱: 779943476@qq.com</p>
     * <p>更新时间: 2019/7/2</p>
     *
     * @param joinPoint 切面数据信息
     */
    @Before("writeLog()")
    public void logRequest(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
        String method = request.getMethod();
        request.setAttribute("requestTime", new Date().getTime());
        String token = request.getHeader("token");
        TokenInfo tokenInfo = null;
        String url = request.getRequestURI();
        String clientIp = IpUtils.getClientIp(request);
        if (token != null && !"".equals(token)) {
            if (joinPoint.getArgs().length > 0) {
                Object o = joinPoint.getArgs()[0];
                if (o instanceof TokenInfo) {
                    tokenInfo = authorizeService.updateToken(token, clientIp);
                    if (tokenInfo.getToken() == null) {
                        throw new OperateException("c005", "你没有权限访问！");
                    }
                    ObjectUtils.convert(o, tokenInfo);
                }
            }
        }
        if (tokenInfo != null) {
            log.info("type=请求，url={},method={},ip={},userId={}", url, method, clientIp, tokenInfo.getUserId());
        } else {
            log.info("type=请求，url={},method={},ip={}", url, method, clientIp);
        }
    }

    /**
     * <p>功能描述: 响应日志记录 </p>
     * <p>更新人: 小程</p>
     * <p>更新描述: 添加方法</p>
     * <p>更新人邮箱: 779943476@qq.com</p>
     * <p>更新时间: 2019/7/2</p>
     *
     * @param joinPoint 切面数据信息
     * @param result    返回数据对象
     */
    @AfterReturning(returning = "result", pointcut = "writeLog()")
    public void logResponse(JoinPoint joinPoint, Object result) {
        if (result != null) {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            String method = request.getMethod();
            Long requestTime = (Long) request.getAttribute("requestTime");
            BigDecimal responseTime = new BigDecimal(new Date().getTime() - requestTime).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP);
            String param = "";
            if (result instanceof List) {
                param = JSONUtils.getStringByList(result);
            } else if (result instanceof String) {
                param = (String) result;
            } else {
                param = JSONUtils.getStringByObject(result);
            }
            log.info("type=响应，url={},method={},ip={},requestTime={},result={}",
                    request.getRequestURI(),
                    method,
                    IpUtils.getClientIp(request),
                    responseTime,
                    param);
        }
    }
}
